﻿using System;
using System.IO;
using System.Linq;
using System.Custom;
using CustomControls;
using System.Drawing;
using HtmlViewControl;
using System.Collections;
using System.Windows.Forms;
using MainModule.Properties;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;

namespace MainModule
{
   public class Emo
   {
      string FRegexPattern;

      public bool Selectable;

      public string FileName;

      public string Transcript;

      public string[] Notations;

      public string RegexPattern
      {
         get
         {
            if (FRegexPattern == null)
            {
               FRegexPattern = "(" + StringExt.Join(Notations.Select(n => Regex.Replace(n, "\\W", new MatchEvaluator((m) =>
               {
                  return "\\" + m.Value;
               }))), "|") + ")";
            }
            return FRegexPattern;
         }
      }

      public string DefaultNotation
      {
         get
         {
            return Notations[0];
         }
      }

      public override string ToString()
      {
         return Notations.Contains(Transcript.ToLower()) ? Transcript : DefaultNotation + " - " + Transcript;
      }
   }

   public class EmoPack
   {
      #region Data

      string FFolder;

      string FRegexPattern;

      string FHtml = @"
                <html>
                  <style>
                     body
                     {{
                        margin: 0;
                        padding: 2;
                        background-color: #9999aa #777788 #777788 #777788;
                     }}
                     img
                     {{
                        cursor: pointer;
                        transition: {0};
                        behavior: clickable;
                     }}
                     img:hover
                     {{
                        transition: image;
                     }}
                     table
                     {{
                        margin: 0;
                        padding: 0;
                     }}
                     popup
                     {{
                        padding: 5;
                        text-align: center;
                     }}
                     table td
                     {{
                        width: {1}px;
                        text-align: center;
                        border-radius: 4;
                     }}
                     table tr
                     {{
                        height: {2}px;
                     }}
                     table td:hover 
                     {{
                        //transition: blend;
                        background-color: yellow yellow orange orange;
                        //background-color: #eef #eef #dde #dde;
                        //background-color: #fff #ccd #ccd #ccd;
                        //background-color: #fff #adf #adf #adf;
                     }}
                  </style>
                  <body>{3}</body>
                </html>";

      Collection<Emo> FEmoticons = new Collection<Emo>();

      #endregion

      public Size EmoSize
      {
         get;
         private set;
      }

      public Size WindowSize
      {
         get;
         private set;
      }

      public string Name
      {
         get
         {
            return new DirectoryInfo(FFolder).Name;
         }
      }

      public string Folder
      {
         get
         {
            return FFolder;
         }
      }

      public string RegexPattern
      {
         get
         {
            if (FRegexPattern == null)
            {
               FRegexPattern = StringExt.Join(FEmoticons.Select(emo => emo.RegexPattern), "|");
            }
            return FRegexPattern;
         }
      }

      public Collection<Emo> Emoticons
      {
         get
         {
            return FEmoticons;
         }
      }

      public EmoPack(string path)
      {
         LoadAsl(path);
      }

      public Emo this[string notation]
      {
         get
         {
            return FEmoticons.FirstOrDefault(emo => emo.Notations.Contains(notation.ToLower()));
         }
      }

      public string GetHtml()
      {
         int n = 0;

         string table = GetEmoPopupHtml() + "<table cellpadding=\"0\" cellspacing=\"0\">";

         Emo[] emos = FEmoticons.Where(emo => emo.Selectable).ToArray();

         for (int i = 0; i < WindowSize.Height && n < emos.Length - 1; i++)
         {
            table += "<tr>";
            for (int j = 0; j < WindowSize.Width && n < emos.Length - 1; j++)
            {
               n = (i * WindowSize.Width) + j;
               table += "<td>";
               table += GetEmoHtml(emos[n], true);
               table += "</td>\r\n";
            }
            table += "</tr>\r\n";
         }
         table += "</table>";

         return string.Format(FHtml, Settings.Default.AlwaysAnimateEmoticons ? "image" : "none", EmoSize.Width, EmoSize.Height, table);
      }

      public string GetEmoHtml(Emo emo, bool popup)
      {
         return "<img class=\"emo\" src=\"" + FFolder + "\\" + emo.FileName + "\" n=\"" + emo.DefaultNotation + "\"" +
                " alt=\"" + emo.Transcript + "\"" +
                (popup ? " titleid=\"" + emo.FileName : " title=\"" + emo.Transcript) + "\"" + " />";
               //(popup ? " titleid=\"" + emo.FileName : "") + "\"" + " />";
      }

      public string GetEmoPopupHtml()
      {
         string html = "";
         foreach (Emo emo in FEmoticons)
         {
            html += "<popup id=\"" + emo.FileName + "\"><img src=\"" + FFolder + "\\" + emo.FileName +
                    "\" /><br>" + emo.Transcript + "</popup>\r\n"; /*"<br>" + "[" + emo.FileName + "]" +*/
         }
         return html;
      }

      public void LoadAsl(string path)
      {
         FFolder = Shell.GetShortPath(Path.GetDirectoryName(path));

         try
         {
            string text = File.ReadAllText(path);

            Match ms = Regex.Match(text, @"SelectionSize\s?=\s?\d{1,2},\s?\d{1,2}", RegexOptions.IgnoreCase);

            if (ms.Success)
            {
               var dim = Regex.Matches(ms.Value, @"\b[0-9]+\b");
               EmoSize = new Size(int.Parse(dim[0].Value), int.Parse(dim[1].Value));
            }

            ms = Regex.Match(text, @"WindowSize\s?=\s?\d{1,2},\s?\d{1,2}", RegexOptions.IgnoreCase);

            if (ms.Success)
            {
               var dim = Regex.Matches(ms.Value, @"\b[0-9]+\b");
               WindowSize = new Size(int.Parse(dim[0].Value), int.Parse(dim[1].Value));
            }

            FEmoticons.Clear();

            foreach (Match l in Regex.Matches(text, "(smiley\\*?\\s?=)\\s?(\".+\")", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace))
            {
               //string[] arr = Regex.Matches(l.Value, "\"[^\"]*\"").Cast<Match>().Select(m => m.Value.Trim('\"')).ToArray();
               string[] arr = l.Value.Split(',').Select(s => s.Trim('\"', ' ')).ToArray();

               if (arr.Length < 4) continue;

               string fileName = arr[0].SubstrAfter("\"");

               if (File.Exists(FFolder + "\\" + fileName))
               {
                  FEmoticons.Add(new Emo()
                  {
                     FileName = fileName,
                     Selectable = arr[1] != "-1",
                     Notations = arr[2].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => n.Trim().ToLower()).ToArray(),
                     Transcript = arr[3]
                  });
               }
            }
         }
         catch (Exception)
         {
            //
         }
      }
   }

   class EmoticonPopup : HtmlPopup
   {
      EmoPack FEmoPack;

      public EmoticonPopup(ContextMenuStrip menu, EmoPack pack)
         : base(menu)
      {
         EmoPack = pack;
      }

      public Emo SelectedEmo
      {
         get;
         private set;
      }

      public EmoPack EmoPack
      {
         get
         {
            return FEmoPack;
         }
         set
         {
            if (value == FEmoPack) return;

            FEmoPack = value;

            UpdateHtml();
         }
      }

      public void UpdateHtml()
      {
         HtmlView.HtmlControlEvent -= htmlView_HtmlControlEvent;
         HtmlView.LoadHtml(FEmoPack.GetHtml(), "");
         HtmlView.HtmlControlEvent += htmlView_HtmlControlEvent;
         ClientSize = new Size(FEmoPack.EmoSize.Width * FEmoPack.WindowSize.Width + 4,
                               FEmoPack.EmoSize.Height * FEmoPack.WindowSize.Height + 4);
      }

      public void LoadEmoPack(string path)
      {
         FEmoPack.LoadAsl(path);
         UpdateHtml();
      }

      public event EventHandler EmoSelected;

      private void htmlView_HtmlControlEvent(object sender, HtmlControlEventArgs e)
      {
         if (e.EventType == HTMLayout.BehaviorEvents.BE_BUTTON_CLICK)
         {
            Menu.Close();

            SelectedEmo = FEmoPack[e.Target["n"]];

            if (EmoSelected != null) EmoSelected(this, EventArgs.Empty);
         }
      }
   }
}
